/**
 *  Copyright 2009 Jonas Lindberg
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package com.blogspot.jlindberg.android.photomailer;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

/**
 * Simple Android application with a somewhat stream lined UI flow for
 * sending new photos via email. 
 * 
 * This can for example be used with Picasa's email upload feature
 * (http://picasa.google.com/support/bin/answer.py?hl=en&answer=83342)
 * to quickly get your photos from the device to your web album.
 * 
 * This code comes with no warranty what so ever.
 * 
 * Note: this does not work well in the Android emulator.
 * 
 * @author Jonas Lindberg, http://jlindberg.blogspot.com.
 */
public class PhotoMailer extends Activity {

  // Preference names as constants.
  private static final String PREF_LAST_MODIFIED = "lastModified";
  private static final String PREF_EMAIL = "email";
  private static final String PREF_SENT_COUNT = "sent_count";
  private static final String PREF_SKIPPED_COUNT = "skipped_count";

  // Returns "/sdcard".
  private final File sdcard = Environment.getExternalStorageDirectory();
  private final String path = "/DCIM/Camera";
  private final File camera = new File(sdcard + path);

  // UI elements.
  private TextView tvSentCount;
  private TextView tvSkippedCount;
  private TextView tvFile;
  private EditText etEmail;
  private Button btnSend;
  private Button btnSkip;
  private Button btnSkip10;

  // Internal state.
  private long lastModified;
  private long sentCount;
  private long skippedCount;

  /** 
   * When the activity is created: add event handlers, load prefs, update UI.
   */
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    tvSentCount = (TextView) findViewById(R.id.tv_sent_count);
    tvSkippedCount = (TextView) findViewById(R.id.tv_skipped_count);
    tvFile = (TextView) findViewById(R.id.tv_file);
    etEmail = (EditText) findViewById(R.id.et_email);
    btnSend = (Button) findViewById(R.id.btn_send);
    btnSkip = (Button) findViewById(R.id.btn_skip);
    btnSkip10 = (Button) findViewById(R.id.btn_skip10);

    btnSend.setOnClickListener(new View.OnClickListener() {
      public void onClick(View v) {
        send();
      }
    });
    btnSkip.setOnClickListener(new View.OnClickListener() {
      public void onClick(View v) {
        skip();
      }
    });
    btnSkip10.setOnClickListener(new View.OnClickListener() {
      public void onClick(View v) {
        skip10();
      }
    });

    SharedPreferences settings = getPreferences(Context.MODE_PRIVATE);
    etEmail.setText(settings.getString(PREF_EMAIL, ""));
    lastModified = settings.getLong(PREF_LAST_MODIFIED, 0);
    sentCount = settings.getLong(PREF_SENT_COUNT, 0);
    skippedCount = settings.getLong(PREF_SKIPPED_COUNT, 0);

    updateUI();
  }

  /**
   * Update UI on resume in case there are new photos.
   */
  @Override
  protected void onResume() {
    super.onResume();
    updateUI();
  }

  /**
   * Store preferences on stop (catches changes to email field).
   */
  @Override
  protected void onStop(){
    super.onStop();
    updateAndStore(lastModified, sentCount, skippedCount);
  }

  /**
   * Send next photo via email.
   */
  private void send() {
    ArrayList<File> files = getCameraFiles(lastModified);
    for (File f : files) {
      Intent i=new Intent(Intent.ACTION_SEND);
      i.putExtra(Intent.EXTRA_EMAIL,
          new String[] { etEmail.getText().toString() });
      i.putExtra(Intent.EXTRA_SUBJECT,"Photo sent with PhotoMailer");
      i.putExtra(Intent.EXTRA_TEXT, "File name: " + f.getName());
      i.putExtra(Intent.EXTRA_STREAM, 
          Uri.parse("file://" + sdcard + path + "/" + f.getName()));
      i.setType("message/rfc822");
      startActivity(Intent.createChooser(i,"PhotoMailer"));
      updateAndStore(f.lastModified(), sentCount + 1, skippedCount);
      break;
    }
    updateUI();
  }

  /**
   * Skip 1 photo.
   */
  private void skip() {
    ArrayList<File> files = getCameraFiles(lastModified);
    for (File f : files) {
      updateAndStore(f.lastModified(), sentCount, skippedCount + 1);
      break;
    }
    updateUI();
  }

  /**
   * Skip 10 photos.
   */
  private void skip10() {
    ArrayList<File> files = getCameraFiles(lastModified);
    int i = 0;
    for (File f : files) {
      if (++i == 10) {
        break;
      }
      updateAndStore(f.lastModified(), sentCount, skippedCount + 1);
    }
    updateUI();
  }

  /**
   * Update UI elements.
   */
  private void updateUI() {
    ArrayList<File> files = getCameraFiles(lastModified);
    if (files.size() > 0) {
      tvFile.setText("Next photo to send: " + files.get(0).getName()
          + " (" + files.size() + " new)");
    } else {
      tvFile.setText("No new photos to send.");
    }
    tvSentCount.setText("Photos sent: " + sentCount);
    tvSkippedCount.setText("Photos skipped: " + skippedCount);
  }

  /**
   * Update and store preferences.
   */
  private void updateAndStore(long lastModified, long sentCount, 
      long skippedCount) { 
    this.lastModified = lastModified;
    this.sentCount = sentCount;
    this.skippedCount = skippedCount;
    SharedPreferences settings = getPreferences(Context.MODE_PRIVATE);
    SharedPreferences.Editor editor = settings.edit();
    editor.putString(PREF_EMAIL, etEmail.getText().toString());
    editor.putLong(PREF_LAST_MODIFIED, lastModified);
    editor.putLong(PREF_SENT_COUNT, sentCount);
    editor.putLong(PREF_SKIPPED_COUNT, skippedCount);
    editor.commit();
  }

  /**
   * Get files in sdcard's camera folder, modified after specified time.
   */
  private ArrayList<File> getCameraFiles(long modifiedAfterTime) {
    ArrayList<File> files = new ArrayList<File>();
    for (File f : camera.listFiles()) {
      if (f.isDirectory()) {
        continue;
      }
      if (f.lastModified() > modifiedAfterTime) {
        files.add(f);
      }
    }
    Collections.sort(files, new LastModifiedComparator());
    return files;
  }

  /**
   * Compare based on File's last modified time. Sort order: increasing.
   */
  private static class LastModifiedComparator implements Comparator<File> {
    public int compare(File f1, File f2) {
      long l = f1.lastModified() - f2.lastModified();
      if (l < 0) { return -1; }
      else if(l > 0) { return 1; }
      else { return 0; }
    }
  }
}